package top.blentle.ai.data.util;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.TypeFactory;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 对象工具集
 * 
 * @author weiwei
 *
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class JsonMapper {

	/**
	 * Jackson ObjectMapper(通用)
	 */
	public static final ObjectMapper om = new ObjectMapper();

	/**
	 * Jackson ObjectMapper(用于比较)
	 */
	public static final ObjectMapper omextra = new ObjectMapper();

	/**
	 * Jackson ObjectMapper(用于Log输出)
	 */
	public static final ObjectMapper omlog = new ObjectMapper();

	static {
		om.setSerializationInclusion(Include.NON_NULL);
		om.enable(SerializationFeature.INDENT_OUTPUT);
		om.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		omextra.setSerializationInclusion(Include.NON_NULL);
		omlog.setSerializationInclusion(Include.NON_NULL);
	}

	/**
	 * 转为JSON字符串
	 *
	 * @param obj
	 *            对象
	 * @return JSON字符串
	 */
	public static String toJson(Object obj) {
		if (obj == null) {
			return null;
		}
		try {
			return om.writeValueAsString(obj);
		} catch (Exception e) {
			throw runtimeException(e);
		}
	}


	/**
	 * 转为JSON字符串，Log输出用，不格式化
	 * 
	 * @param obj
	 *            对象
	 * @return JSON字符串
	 */
	public static String toJsonUnformatted(Object obj) {
		if (obj == null) {
			return null;
		}
		try {
			return omlog.writeValueAsString(obj);
		} catch (Exception e) {
			throw runtimeException(e);
		}
	}

	/**
	 * 自JSON解析对象
	 *
	 * @param json
	 *            JSON字符串
	 * @param cls
	 *            数据类
	 * @return 目标对象
	 */
	public static <T> T fromJson(String json, Class<T> cls) {
		if (json == null || json.trim().isEmpty()) {
			return null;
		}
		try {
			return om.readValue(json, cls);
		} catch (Exception e) {
			throw runtimeException(e);
		}
	}

	/**
	 * 自JSON解析对象,适用于泛型类
	 * 
	 * @param json
	 *            JSON
	 * @param parametrized
	 *            泛型类
	 * @param parameterClasses
	 *            泛型参数类
	 * @return 目标对象
	 */
	public static <P> P fromJson(String json, Class<P> parametrized, Class<?>... parameterClasses) {
		if (json == null || json.trim().isEmpty()) {
			return null;
		}
		try {
			if (parameterClasses == null || parameterClasses.length == 0) {
				return om.readValue(json, parametrized);
			} else {
				return om.readValue(
						json,
						TypeFactory.defaultInstance().constructParametrizedType(parametrized, parametrized,
								parameterClasses));
			}
		} catch (Exception e) {
			throw runtimeException(e);
		}
	}
	
	/**
	 * 转化JSON字符串为JsonNode
	 * @param jsonStr JSON字符创
	 * @return JsonNode对象
	 */
	public static JsonNode readTree(String jsonStr){
		if(jsonStr == null){
			return null;
		}
		try {
			return om.readTree(jsonStr);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 不可变Set
	 * 
	 * @param src
	 *            源
	 * @return 目标Set
	 */
	public static <E> Set<E> unmodifiableSet(Set<E> src) {
		if (src == null) {
			return null;
		}
		return Collections.unmodifiableSet(src);
	}

	/**
	 * 不可变List
	 * 
	 * @param src
	 *            源
	 * @return 目标List
	 */
	public static <E> List<E> unmodifiableList(List<E> src) {
		if (src == null) {
			return null;
		}
		return Collections.unmodifiableList(src);
	}

	/**
	 * 不可变Map
	 * 
	 * @param src
	 *            源
	 * @return 目标Map
	 */
	public static <K, V> Map<K, V> unmodifiableMap(Map<K, V> src) {
		if (src == null) {
			return null;
		}
		return Collections.unmodifiableMap(src);
	}

	/**
	 * 将异常包装为RuntimeException
	 * 
	 * @param e
	 *            异常
	 */
	public static RuntimeException runtimeException(Exception e) {
		if (e instanceof RuntimeException) {
			return (RuntimeException) e;
		}
		return new RuntimeException(e);
	}

	/**
	 * 不区分大小写定位枚举
	 * 
	 * @param enumValues
	 *            枚举值
	 * @param name
	 *            名称
	 * @return 枚举对象
	 */
	public static <T extends Enum<T>> T valueOfIngoreCase(T[] enumValues, String name) {
		if (name == null) {
			throw new NullPointerException("Name is null");
		}
		for (T t : enumValues) {
			if (name.equalsIgnoreCase(t.name())) {
				return t;
			}
		}
		throw new IllegalArgumentException("No enum constant " + name);
	}
	
	/**
	 * 序列化为字节数组
	 * @param obj 要序列化的对象
	 * @return 序列化后的字节数组，若传入的对象为空，则返回空
	 */
	public static byte[] toBytes(Object obj) {
		try {
			return obj != null ? om.writeValueAsBytes(obj) : null;
		} catch (Exception e) {
			throw runtimeException(e);
		}
	}
	
	/**
	 * 从字节数组反序列为对象
	 * @param bs 对象字节数组
	 * @param clazz 对象类型，若传入的bs为null，则返回null
	 * @return
	 */
	public static <T> T fromBytes(byte[] bs, Class<T> clazz) {
		try {
			return bs != null ? om.readValue(bs, clazz) : null;
		} catch (Exception e) {
			throw runtimeException(e);
		}
	}

	public static Object invoke(Class<?> clazz, String methodName, Class<?>[] paramTypes, Object[] params, Object o) {
		try {
			Method method = clazz.getDeclaredMethod(methodName, paramTypes);
			method.setAccessible(true);
			return method.invoke(o, params);
		} catch (Exception e) {
			throw runtimeException(e);
		}
	}

}
